Skip to content

[FEATURE] add pytta.iec60268 with the speech transmission index - #67

Open
aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-sti
Open

aguirreSL wants to merge 1 commit into
PyTTaMaster:developmentfrom
aguirreSL:dev-sti

Conversation

@aguirreSL

@aguirreSL aguirreSL commented Oct 31, 2026 •

Copy link
Copy Markdown

Adds the module pytta.iec60268 with sti(ir, levels=None, noise=None, female=False): the speech transmission index of IEC 60268-16:2011 from an impulse response, by the indirect method of clause 6. It returns the STI, the modulation transfer index of each octave band and the modulation transfer function.

The calculation follows the standard step by step:

  1. The impulse response is filtered into the seven octave bands from 125 Hz to 8 kHz, and the MTF at the 14 modulation frequencies from 0.63 Hz to 12.5 Hz comes from the Schroeder equation of 6.1. When background noise levels are given, it is multiplied by 1 / (1 + 10^(-SNR/10)).
  2. When speech levels in dB SPL are given, the auditory masking of Table A.1, computed from the total level of the band below, and the absolute reception threshold of Table A.2 correct the MTF as in A.5.3. Without levels these corrections are left out, as the note of A.3.1 says for signals not measured in dB SPL.
  3. The effective SNR, limited to 15 dB either way, the transmission index, the MTI and the STI follow A.5.4 to A.5.6, with the male or female weights and redundancies of Table A.3. The STI is limited to 1.

The tests in tests/test_sti.py work out the expected values from the equations of the standard. The tolerance is 0.01 STI, the systematic error that A.5.1.2 allows for the octave filters.

  1. A perfect channel gives STI 1 (0.99 or more with the filters) for both weightings.
  2. At 100 dB in every band, the masking of -10 dB gives 0.8397, against 0.8407 worked out by hand.
  3. With noise at 0 dB SNR the result is 0.4532, against 0.4534 by hand.
  4. The MTF of an exponential decay with T = 1 s follows 1 / sqrt(1 + (2 pi F T / 13.8)^2) within 0.06 in the bands from 2 kHz up. In the lower bands a noise decay fluctuates too much for a fixed tolerance, since the squared envelope of a noise band has few independent values per decay time.
  5. Levels or noise with the wrong number of bands are rejected, and noise needs the speech levels.

STIPA and the direct method are not included.

Checked with Python 3.12, numpy 1.26 and scipy 1.17. The existing tests behave as on development: the 7 failures there (3 in test_h5io.py, 4 in test_pyttasave.py) are the same with and without this change.

Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com

pytta.iec60268.sti gives the STI of IEC 60268-16:2011 from an impulse
response by the indirect method of clause 6: the modulation transfer
function from the Schroeder equation in the seven octave bands and 14
modulation frequencies, the noise term when background levels are
given, the auditory masking of Table A.1 and the reception threshold of
Table A.2 when speech levels are given, and the male or female weights
of Table A.3. It returns the STI, the MTI per band and the MTF.

Tests pin a perfect channel at STI 1, the masking at 100 dB, noise at
0 dB SNR, and the MTF of an exponential decay, within the 0.01 STI that
the standard allows for the octave filters.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant